import { usePermissionStore, usePermissionStoreWithOut } from '/@/store/modules/permission'
import { PageEnum } from '/@/enums/pageEnum'
import { useUserStore, useUserStoreWithOut } from '/@/store/modules/user'
import { warn } from '/@/utils/log'
import { RootRouter, PAGE_NOT_FOUND_ROUTE } from '../constant'
import router from '..'
import projectSetting from '/@/settings/projectSetting'
import { Modal, notification } from 'ant-design-vue'
import { AxiosCanceler } from '@/utils/http/axios/axiosCancel'
import { setRouteChange } from '@/logics/mitt/routeChange'
import { useTransitionSetting } from '@/hooks/setting/useTransitionSetting'
import { unref } from 'vue'
import { useAppStore, useAppStoreWithOut } from '@/store/modules/app'
import nProgress from 'nprogress'

const { closeMessageOnSwitch } = projectSetting

const LOGIN_PATH = PageEnum.BASE_LOGIN

const ROOT_PATH = RootRouter.path

const whitePathList: PageEnum[] = [LOGIN_PATH]

const userStore = useUserStoreWithOut()
const permissionStore = usePermissionStoreWithOut()
const appStore = useAppStoreWithOut()

const { getOpenPageLoading } = useTransitionSetting()

const { removeAllHttpPending } = projectSetting
let axiosCanceler: Nullable<AxiosCanceler>
if (removeAllHttpPending) {
  axiosCanceler = new AxiosCanceler()
}

const isHash = (href: string) => {
  return /^#/.test(href)
}
const body = document.body

const loadedPageMap = new Map<string, boolean>()
const { getOpenNProgress } = useTransitionSetting()
router.beforeEach(async (to: any, from, next) => {
  /**-------------createProgressGuard----------------*/
  unref(getOpenNProgress) && nProgress.start()
  /**-------------createPageGuard----------------*/
  // The page has already been loaded, it will be faster to open it again, you don’t need to do loading and other processing
  to.meta.loaded = !!loadedPageMap.get(to.path)
  // Notify routing changes
  setRouteChange(to)

  // if (!to.meta.loaded) {
  //   return true
  // }
  /**-------------createPageLoadingGuard----------------*/
  if (unref(getOpenPageLoading)) {
    appStore.setPageLoadingAction(true)
    // return true
  }
  /**-------------permissionGuard----------------*/
  if (
    from.path === ROOT_PATH &&
    to.path === PageEnum.BASE_HOME &&
    userStore.getUserInfo.homePath &&
    userStore.getUserInfo.homePath !== PageEnum.BASE_HOME
  ) {
    next(userStore.getUserInfo.homePath)
    return
  }

  /**---------------createHttpGuard--------------*/
  // Switching the route will delete the previous request
  axiosCanceler?.removeAllPending()

  //return true

  const token = userStore.getToken

  // Whitelist can be directly entered
  if (whitePathList.includes(to.path as PageEnum)) {
    if (to.path === LOGIN_PATH && token) {
      const isSessionTimeout = userStore.getSessionTimeout
      try {
        await userStore.afterLoginAction()
        if (!isSessionTimeout) {
          next((to.query?.redirect as string) || '/')
          return
        }
      } catch {}
    }
    next()
    return
  }
  // token or user does not exist
  if (!token) {
    // You can access without permission. You need to set the routing meta.ignoreAuth to true
    if (to.meta.ignoreAuth) {
      next()
      return
    }

    // redirect login page
    const redirectData: { path: string; replace: boolean; query?: Recordable<string> } = {
      path: LOGIN_PATH,
      replace: true,
    }
    if (to.path) {
      redirectData.query = {
        ...redirectData.query,
        redirect: to.path,
      }
    }
    next(redirectData)
    return
  }
  // Jump to the 404 page after processing the login
  if (
    from.path === LOGIN_PATH &&
    to.name === PAGE_NOT_FOUND_ROUTE.name &&
    to.fullPath !== (userStore.getUserInfo.homePath || PageEnum.BASE_HOME)
  ) {
    next(userStore.getUserInfo.homePath || PageEnum.BASE_HOME)
    return
  }
  // get userinfo while last fetch time is empty
  if (userStore.getLastUpdateTime === 0) {
    try {
      await userStore.getUserInfoAction()
    } catch (err) {
      next()
      return
    }
  }
  /**---------------createMessageGuard--------------*/
  try {
    if (closeMessageOnSwitch) {
      Modal.destroyAll()
      notification.destroy()
    }
  } catch (error) {
    warn('message guard error:' + error)
  }
  // return true

  if (permissionStore.getIsDynamicAddedRoute) {
    next()
    return
  }
  const routes = await permissionStore.buildRoutesAction()

  routes.forEach((route) => {
    router.addRoute(route as any)
  })

  router.addRoute(PAGE_NOT_FOUND_ROUTE as any)

  permissionStore.setDynamicAddedRoute(true)
  if (to.name === PAGE_NOT_FOUND_ROUTE.name) {
    // 动态添加路由后，此处应当重定向到fullPath，否则会加载404页面内容
    next({ path: to.fullPath, replace: true, query: to.query })
  } else {
    const redirectPath = (from.query.redirect || to.path) as string
    const redirect = decodeURIComponent(redirectPath)
    const nextData = to.path === redirect ? { ...to, replace: true } : { path: redirect }
    next(nextData)
  }
})

router.afterEach((to) => {
  /**-------------createPageGuard----------------*/
  loadedPageMap.set(to.path, true)
  /**-------------createPageLoadingGuard----------------*/
  if (unref(getOpenPageLoading)) {
    // TODO Looking for a better way
    // The timer simulates the loading time to prevent flashing too fast,
    setTimeout(() => {
      appStore.setPageLoading(false)
    }, 220)
  }
  /**-------------createProgressGuard----------------*/
  unref(getOpenNProgress) && nProgress.done()

  /**-------------stateGuard----------------*/
  if (to.path === PageEnum.BASE_LOGIN) {
    // const tabStore = useMultipleTabStore();
    const userStore = useUserStore()
    const appStore = useAppStore()
    const permissionStore = usePermissionStore()
    appStore.resetAllState()
    permissionStore.resetState()
    // tabStore.resetState();
    userStore.resetState()
    // removeTabChangeListener();
  }
  /**-------------createScrollGuard----------------*/
  // scroll top
  isHash((to as any & { href: string })?.href) && body.scrollTo(0, 0)
})
